import { ObjectID } from "bson";
import { WebSocket, WebSocketServer } from "ws";
import { Db } from "../common";
import { message_list } from "../models/typeinterface";

interface Client{
    ws: WebSocket,
    user: string,
    pwd: string,
    name: string,
    id:ObjectID,
}

interface Message{
    type: string,//消息类型
    data:any
}

interface RelayMessage extends Message{
    receiver: string,
    sender:string
}

    

function query(url:string,key:string):string {
    let pot = url.search(key+"=")
    if (pot == -1) {
        return null
    }
    let str = url.substring(pot+(key+"=").length)
    let x = str.search("&")
    if (x == -1) {
        if (str.search("#") == -1) {
            return decodeURIComponent(str)
        } else {
            return decodeURIComponent(str.substring(0,str.search("#")))
        }
    }
    return decodeURIComponent(str.substring(0,x))
}

async function getFriendsList(id:string) {
    return await (await Db()).collection("friend_list").find({
        $or: [
            {
                userid: id,
                state:1
            },
            {
                friend_userid: id,
                state:1
            }
        ]
    })
}
async function online(id:string) {
    await (await Db()).collection("user").updateOne({
        _id:new ObjectID(id)
    }, {
        $set: {
            online_state:1
        }
    })
    //通知在线的好友
    await (await getFriendsList(id)).forEach((doc) => {
        if (doc.friend_userid != id) {
            let friend = getOnlineUser(doc.friend_userid)
            if (friend) {
                friend.ws.send(JSON.stringify(<Message>{
                    type: "notify",
                    data: {
                        method:"online",
                        onlinestate: 1,
                        userid:id
                    }
                }))
            }
        }
        if (doc.userid != id) {
            let friend = getOnlineUser(doc.userid)
            if (friend) {
                friend.ws.send(JSON.stringify(<Message>{
                    type: "notify",
                    data: {
                        method:"online",
                        onlinestate: 1,
                        userid:id
                    }
                }))
            }
        }
    })
}
async function offline(id:string) {
    await (await Db()).collection("user").updateOne({
        _id:new ObjectID(id)
    }, {
        $set: {
            online_state:0
        }
    })
    //通知在线的好友
    await (await getFriendsList(id)).forEach((doc) => {
        if (doc.friend_userid != id) {
            let friend = getOnlineUser(doc.friend_userid)
            if (friend) {
                friend.ws.send(JSON.stringify(<Message>{
                    type: "notify",
                    data: {
                        method:"offline",
                        onlinestate: 0,
                        userid:id
                    }
                }))
            }
        }
        if (doc.userid != id) {
            let friend = getOnlineUser(doc.userid)
            if (friend) {
                friend.ws.send(JSON.stringify(<Message>{
                    type: "notify",
                    data: {
                        method:"offline",
                        onlinestate: 0,
                        userid:id
                    }
                }))
            }
        }
    })
}
async function getUserInfo(user: string, pwd: string) {
    return await (await Db()).collection("user").findOne({
        user: user,
        pwd:pwd
    })
}
async function saveMessage(sender: string, receiver: string, msg: string, is_read: number) {
    return await (await Db()).collection("message_list").insertOne(<message_list>{
        sender: sender,
        receiver: receiver,
        msg: msg, is_read: is_read,
        add_time:new Date()
    })
}
function getOnlineUser(id: string): Client | null {
    if (ClientMap.has(id)) {
        return ClientMap.get(id);
    }
    return null;
}

let ClientMap:Map<string,Client> = new Map<string,Client>()


//全退出登录
Db().then(async (db) => {
    
    await db.collection("user").updateMany({
        online_state:1
    }, {
        $set: {
            online_state:0
        }
    })
        
    const wss = new WebSocketServer({
        port:3001
    })

    wss.on("connection", async function (client, request) {
        console.log('client connected', request.url);
        let user = query(request.url,"user")
        let pwd = query(request.url,"pwd")
        
        let result =await getUserInfo(user,pwd)
        let client_id:string =""
        if (result) {
            client_id=result._id.toString()
            ClientMap.set(result._id.toString(), <Client>{
                id: result._id,
                user: result.user,
                pwd: result.pwd,
                name: result.name,
                ws:client
            })
            //设置为在线
            await online(client_id)
    
            client.send(JSON.stringify(<Message>{
                type: "connect",
                data: {
                    state:1
                }
            }))
        } else {
            client.send(JSON.stringify(<Message>{
                type: "connect",
                data: {
                    state:0
                }
            }))
            client.close()
            return
        }
    
        client.on("message", async function(data, bin) {
            console.log('receive message');
            let msg: Message = <Message>JSON.parse(data.toString())
            if (msg.type == "relay") {
                let relmsg: RelayMessage = <RelayMessage>msg;
                let receiver: Client = getOnlineUser(relmsg.receiver)
                if (receiver) {
                    //在线直接转发内容（relaymessage）
                    receiver.ws.send(JSON.stringify(msg), async (err) => {
                        if (!err) {
                            //记录聊天信息1
                            await saveMessage(relmsg.sender,relmsg.receiver,relmsg.data.toString(),1)
                        } else {
                            //记录聊天信息0
                            await saveMessage(relmsg.sender,relmsg.receiver,relmsg.data.toString(),0)
                        }
                    })
                } else {
                    //记录聊天信息0
                    await saveMessage(relmsg.sender,relmsg.receiver,relmsg.data.toString(),0)
                }
            }
            if (msg.type == "notify") {
                if (msg.data && msg.data.client && msg.data.client.length) {
                    
                    let newmsg = JSON.parse(JSON.stringify(msg))
                    delete newmsg['client']
                    for (let i = 0; i < msg.data.client.length; i++){
                        let re = getOnlineUser(msg.data.client[i].toString())
                        if (re) {
                            re.ws.send(JSON.stringify(newmsg))
                        }
                    }
                }
            }
        })
        client.on("close", async function (code, rea) {
            console.log('client close',code,rea)
            
            //设置为下线
            await offline(client_id)
        })
    })
    
})